package com.cdtu.controller;


import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.cdtu.entity.*;
import com.cdtu.service.*;
import com.cdtu.util.RedisConst;
import com.cdtu.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.cdtu.util.RedisConst.WATCH_NUMBER;

@Slf4j
@RestController
//解决跨域问题
@CrossOrigin
@RequestMapping("/learning")
public class StudyController {
    @Value("${reggie.pathVideo}")
    private String basePath;
    @Value("${reggie.pathItem}")
    private String ItemPath;
    public static String R_LEARN_PREFIX="topic:record:";
    public static String R_LEARN_PREFIX_RECORD3="learn:record:";
    @Autowired
    private StudyService studyService;

    @Autowired
    private CertifyTypeService certifyTypeService;

    @Autowired
    private UserService userService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private LearnRecordService learnRecordService;

    @Autowired
    private StudyFileController studyFileController;
    /**
     * 分页查询所有视频资源
     * @param pageCurrent
     * @param pageSize
     * @return
     */
    @GetMapping("/queryAll")
    public R getPageAllVideo(Integer pageCurrent, Integer pageSize, String value, String type){
        //构造分页构造器
        log.info("分页查询");
        Page<Study> pageInfo = new Page(pageCurrent, pageSize);
        Page<StudyDTO> studyDTOPage = new Page<>();
        //条件构造器
        LambdaQueryWrapper<Study> queryWrapper = new LambdaQueryWrapper<>();
        //添加过滤条件
        if (value != null) {
            queryWrapper.like(!StrUtil.hasBlank(value),Study::getTitle,value);
        }
        if (type != null){
            queryWrapper.like(!StrUtil.hasBlank(type),Study::getCertifyTypeId,type);
        }
        //添加排序条件
        queryWrapper.orderByDesc(Study::getUpdateTime);

        //执行条件查询
        studyService.page(pageInfo, queryWrapper);

        //对象拷贝
        BeanUtils.copyProperties(pageInfo,studyDTOPage,"records");

        List<Study> records = pageInfo.getRecords();

        List<StudyDTO> list = records.stream().map((item) -> {
            StudyDTO dishDto = new StudyDTO();

            BeanUtils.copyProperties(item,dishDto);

            Long certifyId = item.getCertifyTypeId();//分类id
            //根据id查询分类对象
            CertifyType certifyType = certifyTypeService.getById(certifyId);
            if(certifyType != null){
                String certifyTypeName = certifyType.getName();
                dishDto.setName(certifyTypeName);
            }
            return dishDto;
        }).collect(Collectors.toList());

        studyDTOPage.setRecords(list);

        return R.success(studyDTOPage);
    }

    /**
     * 查询所有视频类型
     * @return
     */
    @GetMapping("/queryType")
    public R queryType(){
        List<CertifyType> type = studyService.findCertifyType();
        if (type != null){
            return R.success(type);
        }
        return R.error("查询错误");
    }

    /**
     * 根据id查询视频资源
     * @param id
     * @return
     */
    @GetMapping("/getEdit/{id}")
    public R getEdit(@PathVariable Long id){
        Study study = studyService.queryById(id);
        if (study != null){
            return R.success(study);
        }
        return R.error("查询错误");
    }

    /**
     * 新建视频资源
     * @param study
     * @return
     */
    @PostMapping("/addVideo")
    public R addVideo(@RequestBody Study study){
        Date date=new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        study.setId(Long.valueOf(format.format(date)));
        study.setPublishTime(date);
        study.setUpdateTime(date);
        study.setDuration(null);
        return R.success(studyService.saveVideosSource(study));
    }

    //弹窗中删除文件
    @DeleteMapping("/deleteVideo/{Src}")
    public R deleteTemporaryVideo(@PathVariable String Src){
        Boolean s=false;
        if (Src.endsWith("mp4")){
            s=studyFileController.uploadCustomPathFile(basePath+Src);
        }else if (Src.endsWith("xls")){
            s=studyFileController.uploadCustomPathFile(ItemPath+Src);
        }else if (Src.endsWith("xlsx")){
            s=studyFileController.uploadCustomPathFile(ItemPath+Src);
        }
        if (s){
            return R.success("删除成功！");
        }else return R.error("删除失败！");
    }


    /**
     * 删除视频资源
     * @param id
     * @return
     */
    @DeleteMapping("/delete/{id}")
    public R deleteVideo(@PathVariable Long id){
        //有外键  先删除对应用户完成的学习记录
        String msg="";
        Study study = studyService.queryById(id);
        String VideoSrc = study.getVedioSrc().substring(study.getVedioSrc().indexOf("=")+1);
        String ItemSrc =study.getTopicSrc().substring(study.getTopicSrc().indexOf("=")+1);
        Boolean s=studyFileController.uploadCustomPathFile(basePath+VideoSrc);
        if (!s){
            msg+="视频文件删除失败！";
        }
        Boolean t=studyFileController.uploadCustomPathFile(ItemPath+ItemSrc);
        if (!t){
            msg+="套题文件删除失败！";
        }
        LambdaQueryWrapper<LearnRecord> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(LearnRecord::getStudyId,id);
        learnRecordService.remove(queryWrapper);
        int count = studyService.deleteVideoById(id);
        if (count>0)
            return R.success("删除成功"+msg);
        return R.error("删除失败"+msg);
    }

    /**
     * 修改视频资源
     * @param request
     * @param study
     * @return
     */
    @PostMapping("/editVideo")
    public R updateVideoData(HttpServletRequest request, @RequestBody Study study){
        String key = RedisConst.TOPIC_RECORD+"*:"+study.getId();
        Boolean delete = redisTemplate.delete(key);
        Date date=new Date();
        SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
        study.setUpdateTime(date);
        int i = studyService.modifyById(study);
        return  R.success(i>0? "true":"false");
    }


    /**
     * 播放视频资源
     * @param id
     * @return
     */
    /*@PostMapping("/playVideo")
    public R playVideo(HttpServletResponse response, int id){
        //条件构造器
        LambdaQueryWrapper<Study> queryWrapper = new LambdaQueryWrapper<>();
        //添加过滤条件
        queryWrapper.eq(!StringUtils.isEmpty(id),Study::getId,id);
        Study study = studyService.getOne(queryWrapper);
        if (study == null){
            return R.error("视频不存在");
        }
        try {
            //设置响应内容类型。
            response.setContentType("video/mp4");
            // 创建文件输入流，读取服务器的文件。
            FileInputStream fileInputStream = new FileInputStream(new File(study.getVedioSrc()));
//            System.out.println("文件名"+name);
            int len = 0;
            byte[] bytes = new byte[1024];
            // 获取文件输出流，以写数据到前端。
            ServletOutputStream outputStream = response.getOutputStream();
            // 循环读取
            while ((len = fileInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                // 刷新
                outputStream.flush();
            }
            // 关闭资源
            fileInputStream.close();
            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return R.success("播放成功");
    }*/

    /**
     * 查询某具体某人每个模块的进度
     * @return
     */
    @Transactional
    @GetMapping("/queryTypeByUid/{oid}")
    public R queryTypeByUid(@PathVariable("oid") String oid){
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);
//        String key= R_LEARN_PREFIX_RECORD1+user.getId();
//        //先从缓存中拿取，缓存中没有再查询数据库
//        String json = redisTemplate.opsForValue().get(key);
//        StudyDTO studyDTO = JSONUtil.toBean(json, StudyDTO.class);
//
//        if (BeanUtil.isNotEmpty(studyDTO.getStudyRecord1List())){
//            return R.success(studyDTO.getStudyRecord1List());
//        }

//        第一次直接去数据库查询,并且将这个人的进度信息注册到学习记录中，如果是老用户，可以直接去查询进度

        List<CertifyType> type = studyService.findCertifyType();
        List<CertifyTypeVO> voList=new ArrayList<>();
        //遍历每种类型
        for (CertifyType certifyType : type) {
            int notFinishSum=0;
            CertifyTypeVO vo=new CertifyTypeVO();
            Long cid = certifyType.getId();
            vo.setId(cid);
            vo.setName(certifyType.getName());
            vo.setImageSrc(certifyType.getImageSrc());
            //每种类型的题目集合，查询课集合
            LambdaQueryWrapper<Study> studyQueryWrapper=new LambdaQueryWrapper<>();
            studyQueryWrapper.eq(Study::getCertifyTypeId,cid);
            List<Study> list = studyService.list(studyQueryWrapper);

//            老用户直接去进度表查询
            for (Study study : list) {
                Long sid = study.getId();
                LambdaQueryWrapper<LearnRecord> recordWrapper=new LambdaQueryWrapper<>();
                recordWrapper.eq(LearnRecord::getStudyId,sid).eq(LearnRecord::getUserId,user.getId());
                LearnRecord record = learnRecordService.getOne(recordWrapper);
                if (record==null){
                    record=new LearnRecord();
                    record.setStudyId(study.getId());
                    record.setIsfinished(0);
                    record.setUserId(user.getId());
                    boolean save = learnRecordService.save(record);
                    if (!save){
//                        System.out.println(save);
                        return R.error("加载失败，请重新尝试");
                    }
                }else {

                    if (record.getIsfinished()==1){
                        notFinishSum++;
                    }
                }
                vo.setIsFinishTotal(notFinishSum);
            }

            //新用户存数据
//            List<LearnRecord> recordList=new ArrayList<>();
//            for (Study study : list) {
//                LearnRecord record=new LearnRecord();
//                record.setStudyId(study.getId());
//                record.setIsfinished(0);
//                record.setUserId(user.getId());
//                recordList.add(record);
//            }
//            boolean result = learnRecordService.saveBatch(recordList);

//            if (result){
//                System.out.println(result);
//                return R.error("加载失败，请重新尝试");
//            }
            vo.setTopicTotal(list.size());

//            拿到之后需要将这个人的所有进度存储到数据库中
            //查询志愿者具体某一套题的进度，我们需要查询二级学习进度，先将数据存到缓存中
//            String jsonRecord2=redisTemplate.opsForValue().get(R_LEARN_PREFIX+cid+":"+user.getId());
//            List<StudyRecord2DTO> studyRecord2List = JSONUtil.toBean(jsonRecord2, StudyDTO.class).getStudyRecord2List();
//            long count = studyRecord2List.stream().filter(studyRecord2DTO -> studyRecord2DTO.getIsFinish() == 1).count();
//            vo.setIsFinishTotal(count);
            voList.add(vo);
        }
//        将查询到的数据存到数据库中
//        StudyDTO learnRecord1=new StudyDTO();
//        learnRecord1.setStudyRecord1List(voList);
//        String jsonStr = JSONUtil.toJsonStr(learnRecord1);
//        redisTemplate.opsForValue().set(key,jsonStr);

        return R.success(voList);
    }

    /**
     * 根据id查询视频集合
     * @param oid
     * @return
     */
    @GetMapping("/getAllVideo/{cid}/{oid}")
    public R getAllVideo(@PathVariable("cid") long cid,
                         @PathVariable("oid") String oid){

//        System.out.println("查询错误结果"+oid);
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);
        //刚开始休要去缓存中获取，如果缓存没有，再去数据库中查询
//        String key= R_LEARN_PREFIX+cid+":"+user.getId();
//
//        String json = redisTemplate.opsForValue().get(key);
//        StudyDTO studyDTO = JSONUtil.toBean(json, StudyDTO.class);
//
//        if (BeanUtil.isNotEmpty(studyDTO.getStudyRecord2List())){
//            return R.success(studyDTO.getStudyRecord2List());
//        }
        //从数据库中查询到的肯定是全新没有进度的
        LambdaQueryWrapper<Study> studyQueryWrapper=new LambdaQueryWrapper<>();
        studyQueryWrapper.eq(Study::getCertifyTypeId,cid);
        List<Study> list = studyService.list(studyQueryWrapper);
        List<StudyRecord2DTO> dtoList=new ArrayList<>();
        for (Study study : list) {
            StudyRecord2DTO dto=new StudyRecord2DTO();
            Long sid = study.getId();
            LambdaQueryWrapper<LearnRecord> recordWrapper=new LambdaQueryWrapper<>();
            recordWrapper.eq(LearnRecord::getStudyId,sid).eq(LearnRecord::getUserId,user.getId());
            LearnRecord record = learnRecordService.getOne(recordWrapper);
            dto.setId(sid);
            dto.setIsFinish(record.getIsfinished());
            dto.setTitle(study.getTitle());
            dto.setTopicSrc(study.getTopicSrc());
            dtoList.add(dto);
        }
//        将查询到的数据存到数据库中
//        StudyDTO learnRecord2=new StudyDTO();
//        learnRecord2.setStudyRecord2List(dtoList);
//        String jsonStr = JSONUtil.toJsonStr(learnRecord2);
//        redisTemplate.opsForValue().set(key,jsonStr);
        return R.success(dtoList);
    }

    /**
     * 根据id查询视频资源
     * @param id
     * @return
     */
    @PutMapping("/changeStatus/{id}/{oid}")
    public R getEdit(@PathVariable("id") long id,
                     @PathVariable("oid") String oid){

//        拿出二级缓存的所有数据，更改，然后继续存数据库
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);
        Long uid = user.getId();
        LambdaQueryWrapper<LearnRecord> recordWrapper=new LambdaQueryWrapper<>();
        recordWrapper.eq(LearnRecord::getStudyId,id).eq(LearnRecord::getUserId,uid);
        LearnRecord record = learnRecordService.getOne(recordWrapper);
        record.setIsfinished(1);
        boolean update = learnRecordService.updateById(record);



//        直接去数据库修改状态

        //刚开始休要去缓存中获取，如果缓存没有，再去数据库中查询
//        String key= R_LEARN_PREFIX+cid+":"+user.getId();
////
//        String json = redisTemplate.opsForValue().get(key);
//        StudyDTO studyDTO = JSONUtil.toBean(json, StudyDTO.class);

//        if (BeanUtil.isNotEmpty(studyDTO.getStudyRecord2List())){
//            return R.success(studyDTO.getStudyRecord2List());
//        }
//        List<StudyRecord2DTO> studyRecord2List = studyDTO.getStudyRecord2List();
//
//        for (StudyRecord2DTO record2DTO : studyRecord2List) {
//           if (record2DTO.getId()==id){
//               record2DTO.setIsFinish(1);
//               break;
//           }
//        }
//        studyDTO.setStudyRecord2List(studyRecord2List);
//        String jsonStr = JSONUtil.toJsonStr(studyDTO);
//        redisTemplate.opsForValue().set(key,jsonStr);

        //更改了二级缓存，也需要更改一级缓存

        return R.success("修改成功");
    }


    @GetMapping("/setTopic/{id}/{oid}")
    public R setTopic(@PathVariable("id") long id,
                      @PathVariable("oid") String oid){
//        System.out.println("课"+id);
//        System.out.println("ren"+oid);
//        先去缓存中查找，有则直接返回
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);
        Long uid = user.getId();
        String key = R_LEARN_PREFIX+uid+":"+id;
        Boolean aBoolean = redisTemplate.hasKey(key);
//        System.out.println("缓存存在么"+aBoolean);
        if (aBoolean){
//            String json = redisTemplate.opsForValue().get(key);
            String json = redisTemplate.opsForList().index(key, -1);
            ProgressDTO progressDTO = JSONUtil.toBean(json, ProgressDTO.class);
            progressDTO.setSubmit(true);
//            System.out.println(progressDTO);
//            List<Topic> topicList = progressDTO.getTopicList();
            return R.success(progressDTO);
//            if (topicList!=null){
//                System.out.println("查询缓存");
//                return R.success(topicList);
//            }
        }


        List<Topic> topicList = new ArrayList<>();

        /*//条件构造器
        LambdaQueryWrapper<Study> queryWrapper = new LambdaQueryWrapper<>();
        //添加过滤条件
        queryWrapper.eq(!StringUtils.isEmpty(id),Study::getId,id);
        Study study = studyService.getOne(queryWrapper);
        if (study == null){
            return R.error("找不到该文件");
        }*/
        try {
            Study study = studyService.getById(id);
//            XSSFWorkbook xssfWorkbook = new XSSFWorkbook("E:\\study\\Item\\20230410214656急救AED.xlsx");
            String topicSrc = study.getTopicSrc();
            String[] split = topicSrc.split("=");
            String filePath = split[1];
            XSSFWorkbook xssfWorkbook = new XSSFWorkbook(ItemPath+filePath);
            System.err.println(ItemPath+filePath);
            XSSFSheet sheet = xssfWorkbook.getSheetAt(0);

            int lastRowNum = sheet.getLastRowNum();

            for (int i = 1; i < lastRowNum+1; i++) {
                XSSFRow row = sheet.getRow(i);
                char A = 'A';
                if (row != null){
                    List<Option> optionList = new ArrayList<>();
                    List<String> list = new ArrayList<>();
                    for (Cell cell: row) {
                        cell.setCellType(Cell.CELL_TYPE_STRING);
                        String value = cell.getStringCellValue();
                        if (cell.getColumnIndex()>2 && cell.getColumnIndex()<9){
                            if (!value.equals("null") && !value.equals("")){
                                Option option = new Option(String.valueOf(A),value,false);
                                optionList.add(option);
                                A++;
                            }
                        }else {
                            list.add(value);
                        }
                            /*if (value !=null && !"".equals(value)) {
                                list.add(value);
                            }*/
                    }
                    if (list.size()>0) {
                        Topic topic = new Topic(Integer.parseInt(list.get(0)),list.get(1),Integer.parseInt(list.get(2)),optionList,list.get(3),list.get(4));
                        topic.setChecked(false);
                        topicList.add(topic);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        ProgressDTO progressDTO=new ProgressDTO();
        progressDTO.setTopicList(topicList);
        progressDTO.setClassId(id);
        progressDTO.setTitle(studyService.getById(id).getTitle());

        return R.success(progressDTO);
    }

    @GetMapping("/classDetail/{sid}/{oid}")
    public R classDetail(@PathVariable("sid") long sid,
                         @PathVariable("oid") String oid){
//        System.out.println(sid);
//        System.out.println(oid);
//        studyService.getById(sid);
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);
        redisTemplate.opsForSet().add(WATCH_NUMBER+sid,oid);

//        先去缓存查询,缓存没有就去数据库查询，第一次肯定去数据库查询
        String key=R_LEARN_PREFIX_RECORD3+user.getId()+":"+sid;
        Boolean aBoolean = redisTemplate.hasKey(key);
        Long size = redisTemplate.opsForSet().size(WATCH_NUMBER + sid);
//        System.out.println("缓存对象"+aBoolean);
        if (aBoolean){
            StudyDTO studyDTO = JSONUtil.toBean(redisTemplate.opsForValue().get(key), StudyDTO.class);
            studyDTO.setWatchNumber(size);
            return R.success(studyDTO);
        }
        Study study = studyService.getById(sid);
        StudyDTO dto=new StudyDTO();
        BeanUtils.copyProperties(study,dto);
        dto.setInitialTime(0);

//        R_LEARN_PREFIX_RECORD3
        String jsonStr = JSONUtil.toJsonStr(dto);
        redisTemplate.opsForValue().set(key,jsonStr);
        dto.setWatchNumber(size);
        return  R.success(dto);
    }
    /**
     * 存储视频进度
     * @param sid:
     * @param oid:
     * @param initial:
     * @return R
     * @author Sakura
     * @date 2023/3/8 21:36
     */
    @PutMapping("/changeProgress/{sid}/{oid}/{initial}")
    public R changeProgress(@PathVariable("sid") long sid,
                            @PathVariable("oid") String oid,
                            @PathVariable("initial") double initial){
//        System.out.println(sid);
//        System.out.println(oid);
//        studyService.getById(sid);
//        System.out.println("initial_time"+initial);
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);

//        先去缓存查询,缓存没有就去数据库查询，第一次肯定去数据库查询
        String key=R_LEARN_PREFIX_RECORD3+user.getId()+":"+sid;
        StudyDTO studyDTO = JSONUtil.toBean(redisTemplate.opsForValue().get(key), StudyDTO.class);
        studyDTO.setInitialTime(initial);
        String jsonStr = JSONUtil.toJsonStr(studyDTO);
        redisTemplate.opsForValue().set(key,jsonStr);
        return  R.success("成功");
    }

    /**
     * 保存做题的进度
     * @param oid:
     * @param sid:
     * @param dto:
     * @return R
     * @author Sakura
     * @date 2023/3/8 21:35
     */
    @RequestMapping("/saveProgress/{oid}/{sid}")
    public R saveProgress(@PathVariable("oid") String oid,
                          @PathVariable("sid") String sid,
                          @RequestBody ProgressDTO dto){
        //算分
        double score=0;
        int size= dto.getTopicList().size();
        int count=0;
        List<Topic> topicList = dto.getTopicList();
        for (Topic topic : topicList) {
            if (topic.isCorrect()){
                count++;
            }
        }
        score = (100.0/size) * count;
        score = Double.parseDouble(String.format("%.2f",score));
        dto.setSubmitScore(score);

        dto.setFinishedTime(new Date());
        LambdaQueryWrapper<User> queryWrapper=new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getOpenid,oid);
        User user = userService.getOne(queryWrapper);
        String key = R_LEARN_PREFIX+user.getId()+":"+sid;
        String jsonStr = JSONUtil.toJsonStr(dto);


        //redisTemplate.opsForValue().set(key,jsonStr);
        redisTemplate.opsForList().rightPush(key,jsonStr);
//        System.out.println(dto.getTopicList());
        return R.success("成功");
    }
    /**
     *  根据 类型id获取 课程的描述
     * @author wp
     * @param
     * @date 2023/4/11 10:30
     * @return
     */
    @GetMapping("studyDescription/{typeId}")
    public  R getStudyDescription(@PathVariable("typeId") long typeId ){
//        Map<String,String> study=new HashMap<>();
//        study.put("description",certifyTypeService.getById(typeId).getDescription());
//        study.put("imageScr",certifyTypeService.getById(typeId).getImageSrc());
//        return R.success(study);
        return R.success( certifyTypeService.getById(typeId).getDescription());
    }
}
